/*
 * Clase lectora de archivos y flujos de datos.
 * 
 * @ Project: Compiler
 * @ File Name: SourceReader.java
 * @ Date: 21/09/2008
 */
package cml.scanning;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class SourceReader {
	
	// Constants
	
	public static final char EOF = '\u0000';
	
	// Fields
	
	private final List<String> lines = new ArrayList<String>();
	private int indexOfCurrentLine = 0;
	private int indexOfNextCharInLine = 0;
	
	@Deprecated
	@SuppressWarnings("unused")
	private String file_name;
	
	// Constructors
	
	/**
	 * @throws java.io.FileNotFoundException
	 *           If the file identified by the specified file name cannot be read.
	 * @throws java.io.IOException
	 *           If an I/O error occurs when reading the source.
	 */
	public SourceReader(String file_name) throws IOException {
		
		// this.file_name = file_name;
		
		final BufferedReader reader = new BufferedReader(new FileReader(file_name));
		readAndReleaseSource(reader);
	}
	
	/**
	 * @throws NullPointerException
	 *           If the specified input stream is {@code null}.
	 * @throws java.io.IOException
	 *           If an I/O error occurs when reading the source.
	 */
	public SourceReader(final InputStream in) throws IOException {
		if (in == null) throw new NullPointerException();
		final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		readAndReleaseSource(reader);
	}
	
	// View operations
	
	public synchronized char getNextChar() {
		if (indexOfCurrentLine < lines.size()) {
			final String line = lines.get(indexOfCurrentLine) + "\n";
			if (indexOfNextCharInLine >= line.length()) {
				indexOfCurrentLine++;
				indexOfNextCharInLine = 0;
				return getNextChar();
			}
			return line.charAt(indexOfNextCharInLine++);
		}
		return EOF;
	}
	
	public synchronized void ungetNextChar() {
		if (indexOfCurrentLine >= lines.size()) {
			indexOfCurrentLine = lines.size() - 1;
			indexOfNextCharInLine = lines.get(indexOfCurrentLine).length() - 1;
			return;
		}
		if (indexOfNextCharInLine <= 0) {
			if (indexOfCurrentLine > 0) {
				--indexOfCurrentLine;
				indexOfNextCharInLine = lines.get(indexOfCurrentLine).length() - 1;
			}
		} else {
			indexOfNextCharInLine--;
		}
	}
	
	// Helper operations
	
	private void readAndReleaseSource(final BufferedReader reader)
	    throws IOException {
		String line;
		while ((line = reader.readLine()) != null) {
			lines.add(line);
		}
		reader.close();
	}
	
	public int getCurrentLine(){
		
		return this.indexOfCurrentLine;
	}
	
}
